/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GlbLib-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_06_01			*/
/*	File:		GlbEpoll.cpp			*/
/********************************************************/

#include "GlbEpoll.h"

namespace GlbNet
{

CGlbEpoll::CGlbEpoll()
{
	m_pCNet = NULL;
	m_pFunction = NULL;
	m_iEpoll = GLB_FAILURE;
}

CGlbEpoll::~CGlbEpoll()
{
	GlbEpollClose();
	m_pCNet = NULL;
	m_pFunction = NULL;
}

void CGlbEpoll::GlbEpollSetFunction(int (*pFunction)(int))
{
	m_pFunction = pFunction;

	return;
}

void CGlbEpoll::GlbEpollClose()
{
	if (m_iEpoll > 0) {
		close(m_iEpoll);
	}

	return;
}

int CGlbEpoll::GlbEpollCreate()
{
	m_iEpoll = epoll_create(GLB_EPOLL);

	return m_iEpoll;
}

void CGlbEpoll::GlbEpollPutEpoll(int iEpoll)
{
	m_iEpoll = iEpoll;

	return;
}

int CGlbEpoll::GlbEpollGetEpoll()
{
	return m_iEpoll;
}

void CGlbEpoll::GlbEpollCloseNet()
{
	if (NULL != m_pCNet) {
		m_pCNet->GlbNetClose();
		delete(m_pCNet);
	}

	return;
}

void CGlbEpoll::GlbEpollPutNet(CGlbNet* pCNet)
{
	m_pCNet = pCNet;

	return;
}

CGlbNet* CGlbEpoll::GlbEpollGetNet()
{
	return m_pCNet;
}

int CGlbEpoll::GlbEpollUdpInit(char* pszPort)
{
	return GLB_SUCCESS;
}

void CGlbEpoll::GlbEpollUdpWait()
{
	return;
}

int CGlbEpoll::GlbEpollTcpInit(char* pszPort)
{
	if (GLB_FAILURE != GlbEpollCreate()) {
		m_pCNet = new CGlbTcp();
		if (GLB_SUCCESS == ((CGlbTcp*)m_pCNet)->GlbTcpInit(pszPort) ) {
			if (GLB_SUCCESS == m_pCNet->GlbNetSetNonBlock()) {
				GlbEpollGlblAdd(m_pCNet->GlbNetGetSocket());
			}
			else {
				GLB_ERROR("Failed to GlbNetSetNonBlock\n");
				goto GlbError;
			}
		}
		else {
			GLB_ERROR("Failed to GlbTcpInit\n");
			goto GlbError;
		}
	}
	else {
		GLB_ERROR("Failed to GlbEpollCreate\n");
		goto GlbError;
	}

	return GLB_SUCCESS;

GlbError:
	m_pCNet->GlbNetClose();
	delete(m_pCNet);

	return GLB_FAILURE;
}

void CGlbEpoll::GlbEpollTcpWait()
{
	int iCount = 0;
	int iTotal = 0;
	int iSocket = 0;
	struct epoll_event stEpoll;
	struct sockaddr_in stClient;
	struct epoll_event stEvent[GLB_EVENT];
	socklen_t iClient = sizeof(struct sockaddr_in);

	while (true) {
		memset(&stEvent, '\0', sizeof(stEvent));
		iTotal = GlbEpollWait(stEvent, GLB_EVENT);
		for (iCount = 0; iCount < iTotal; iCount ++) {
			memset(&stEpoll, '\0', sizeof(struct epoll_event));
			if (stEvent[iCount].data.fd == m_pCNet->GlbNetGetSocket()) {
				while ((iSocket = accept(m_pCNet->GlbNetGetSocket(), (struct sockaddr*)&stClient, &iClient)) > 0) {
					fcntl(iSocket, F_SETFL, fcntl(iSocket, F_GETFL, 0) | O_NONBLOCK);
					stEpoll.events = EPOLLIN | EPOLLET;
					stEpoll.data.fd = iSocket;
					GlbEpollGlblAdd(&stEpoll);
				}
			}
			else {
				if (0 == (*m_pFunction)(stEvent[iCount].data.fd)) {
					stEpoll.data.fd = stEvent[iCount].data.fd;
					close(stEvent[iCount].data.fd);
					GlbEpollGlblDel(&stEpoll);
				}
			}
		}
	}

	return;
}

} /* GlbNet */
